package com.yugao.fintech.antelope.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yugao.fintech.antelope.system.assembly.SysTenantAssembly;
import com.yugao.fintech.antelope.system.manager.SysMqManager;
import com.yugao.fintech.antelope.system.manager.SysTenantManager;
import com.yugao.fintech.antelope.system.manager.SysTenantPackageManager;
import com.yugao.fintech.antelope.system.mapper.SysTenantPackageMapper;
import com.yugao.fintech.antelope.system.model.entity.SysTenant;
import com.yugao.fintech.antelope.system.model.entity.SysTenantPackage;
import com.yugao.fintech.antelope.system.model.rqrs.tenant.*;
import com.yugao.fintech.antelope.system.service.SysTenantPackageService;
import com.yugao.fintech.framework.assistant.utils.StringUtils;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import com.yugao.fintech.framework.mybatisplus.utils.PageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SysTenantPackageServiceImpl extends ServiceImpl<SysTenantPackageMapper, SysTenantPackage> implements SysTenantPackageService {
    @Autowired
    private SysTenantAssembly tenantAssembly;
    @Autowired
    private SysTenantPackageManager tenantPackageManager;
    @Autowired
    private SysTenantManager tenantManager;
    @Autowired
    private SysMqManager mqManager;

    @Override
    public Long saveTenantPackage(TenantPackageSaveReq req) {
        SysTenantPackage tenantPackage = tenantAssembly.toTenantPackage(req);
        this.save(tenantPackage);
        return tenantPackage.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTenantPackage(TenantPackageUpdateReq req) {
        SysTenantPackage tenantPackage = tenantAssembly.toTenantPackage(req);
        // 校验租户
        tenantPackageManager.validTenantPackage(req.getId());
        // 更新
        this.updateById(tenantPackage);

        List<SysTenant> tenants = tenantManager.listByPackageId(req.getId());

        // 异步更新租户
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

            @Override
            public void afterCommit() {
                tenants.forEach(mqManager::sendUpdateTenantMsg);
            }

        });
    }

    @Override
    public void deleteTenantPackage(Long id) {
        // 校验租户
        tenantPackageManager.validTenantPackage(id);
        // 查看租户套餐是否还有被引用的
        if (tenantManager.countByPackageId(id) > 0) {
            throw new BizException("有租户关联当前套餐, 不可删除");
        }
        this.removeById(id);
    }

    @Override
    public TenantPackageResp getTenantPackage(Long id) {
        SysTenantPackage tenantPackage = this.getById(id);
        return tenantAssembly.toTenantPackageResp(tenantPackage);
    }

    @Override
    public IPage<TenantPackageResp> pageTenantPackage(TenantPackagePageReq req) {
        LambdaQueryWrapper<SysTenantPackage> lqw = SysTenantPackage.lqw()
                .eq(Objects.nonNull(req.getStatus()), SysTenantPackage::getStatus, req.getStatus())
                .like(StringUtils.isNotEmpty(req.getName()), SysTenantPackage::getName, req.getName());

        IPage<SysTenantPackage> page = this.page(PageUtil.to(req), lqw);
        return PageUtil.to(page, e -> tenantAssembly.toTenantPackageResp(e));
    }

    @Override
    public List<TenantPackageResp> listTenantPackage(TenantPackageListReq req) {
        LambdaQueryWrapper<SysTenantPackage> lqw = SysTenantPackage.lqw()
                .eq(StringUtils.isNotEmpty(req.getStatus()), SysTenantPackage::getStatus, req.getStatus())
                .eq(Objects.nonNull(req.getSceneId()), SysTenantPackage::getSceneId, req.getSceneId());
        return this.list(lqw).stream().map(tenantAssembly::toTenantPackageResp).collect(Collectors.toList());
    }
}
